﻿using System;
using Netbits.Common.Threading;

namespace Netbits.TelnetServer.Parameters
{
	/// <summary>
	/// Represents the base class of all Command-Parameters.
	/// </summary>
	public abstract class ParameterBase : IComparable, IDisposable
	{
		#region Private Variables

		/// <summary>
		/// Name of this parameter
		/// </summary>
		readonly protected string _Name;
		/// <summary>
		/// Lock instance to lock properties.
		/// </summary>
		protected Lock _Lock;
		/// <summary>
		/// Name of the parameter-type
		/// </summary>
		readonly protected string _Typename;
		/// <summary>
		/// If any value is set this is true
		/// </summary>
		protected bool _HasValue;
		/// <summary>
		/// If any default-value is set this is true
		/// </summary>
		protected bool _HasDefaultValue;
		string _Description;
		bool _MustSet;
		bool _IsSet;
		bool _Invisible;
		bool _Disposed;

		#endregion

		#region Constructor

		/// <summary>
		/// Default-Constructor needs the name of this parameter.
		/// </summary>
		/// <param name="Name_">Name of this parameter</param>
		public ParameterBase( string Name_, string Typename_ )
		{
			_Lock = new Lock();
			_Name = Name_;
			_Typename = Typename_;
		}

		#endregion

		#region Public Properties

		/// <summary>
		/// Returns the name of the parameter.
		/// </summary>
		public string Name
		{
			get
			{
				return _Name;
			}
		}

		/// <summary>
		/// Returns the description of the parameter or set this.
		/// </summary>
		public string Description
		{
			get
			{
				using( _Lock.Read() )
					return _Description;
			}
			set
			{
				using( _Lock.Write() )
					_Description = value;
			}
		}

		/// <summary>
		/// Returns if the parameter must set or set this.
		/// </summary>
		public bool MustSet
		{
			get
			{
				using( _Lock.Read() )
					return _MustSet;
			}
			set
			{
				using( _Lock.Write() )
					_MustSet = value;
			}
		}

		/// <summary>
		/// Returns if this parameter is set from the client on active command.
		/// </summary>
		public bool IsSet
		{
			get
			{
				using( _Lock.Read() )
					return _IsSet;
			}
			internal set
			{
				using( _Lock.Write() )
					_IsSet = true;
			}
		}

		/// <summary>
		/// Returns if this parameter is invisible or set this.
		/// </summary>
		public bool Invisible
		{
			get
			{
				using( _Lock.Read() )
					return _Invisible;
			}
			set
			{
				using( _Lock.Write() )
					_Invisible = value;
			}
		}

		/// <summary>
		/// Returns the name of this parameter-type
		/// </summary>
		public string Typename
		{
			get
			{
				return _Typename;
			}
		}

		/// <summary>
		/// Returns if the value is set or has a default-value.
		/// </summary>
		public bool IsValueSet
		{
			get
			{
				using( _Lock.Read() )
				{
					if( !_HasValue )
					{
						if( !_HasDefaultValue )
							return false;
					}

					return true;
				}
			}
			protected set
			{
				using( _Lock.Write() )
					_HasValue = value;
			}
		}

		#endregion

		#region Internal Functions

		/// <summary>
		/// Reset values for this parameters.
		/// Must call from inherit class!
		/// </summary>
		internal virtual void ResetValues()
		{
			_IsSet = false;
		}

		/// <summary>
		/// Print specified information for this parameter.
		/// </summary>
		/// <param name="Search_">Search-string</param>
		/// <param name="Session_">The client session</param>
		internal virtual void PrintInfo( NetbitsTelnetClientSession Session_, string Search_ )
		{
			if( !string.IsNullOrEmpty( _Description ) )
				Session_.Send( _Description );
		}

		/// <summary>
		/// Set the value for this parameter.
		/// Must call from inherit class!
		/// </summary>
		/// <param name="Value_">Value to set.</param>
		internal virtual void SetValue( string Value_ )
		{
			_HasValue = true;
		}

		/// <summary>
		/// Copy all data from specified parameter. 
		/// Must call from inherit class!
		/// </summary>
		/// <param name="Parameter_"></param>
		internal virtual void CopyFrom( ParameterBase Parameter_ )
		{
			_HasDefaultValue = Parameter_._HasDefaultValue;
			_HasValue = Parameter_._HasValue;
			_IsSet = Parameter_._IsSet;
			_Description = Parameter_._Description;
			_MustSet = Parameter_._MustSet;
			_Invisible = Parameter_._Invisible;
		}

		#endregion

		#region Protected Functions

		/// <summary>
		/// Dispose parameter resources 
		/// Must call from inhered class
		/// </summary>
		/// <param name="Disposing_">Dispose managed resources</param>
		protected virtual void Dispose( bool Disposing_ )
		{
			if( !_Disposed )
			{
				if( Disposing_ )
				{
					if( _Lock != null )
					{
						_Lock.Dispose();
						_Lock = null;
					}
				}

				_Disposed = true;
			}
		}

		#endregion

		#region IComparable

		/// <summary>
		/// Compare to instance of parameters
		/// </summary>
		/// <param name="obj">ParameterBase instance</param>
		/// <returns>0 if is the same</returns>
		public virtual int CompareTo( object obj )
		{
			ParameterBase pb = obj as ParameterBase;
			if( pb == null )
				return -1;

			return _Name.CompareTo( pb.Name );
		}

		#endregion

		#region IDisposable

		/// <summary>
		/// Dispose parameter resources
		/// </summary>
		public void Dispose()
		{
			Dispose( true );
			GC.SuppressFinalize( this );
		}

		#endregion
	}
}
